package com.zxq.ruoyi.controller;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.zxq.factory.enums.EField;
import com.zxq.ruoyi.domain.*;
import com.zxq.ruoyi.domain.vo.*;
import com.zxq.ruoyi.domain.vo.item.DecodeObj;
import com.zxq.ruoyi.domain.vo.item.EncodeObj;
import com.zxq.ruoyi.service.impl.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.zxq.ruoyi.service.IIotCmdService;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.utils.poi.ExcelUtil;

/**
 * 指令Controller
 * 
 * @author ruoyi
 * @date 2022-09-16
 */
@RestController
@RequestMapping("/cmd")
public class IotCmdController extends BaseController {
    /**
     * 指令服务
     */
    @Autowired
    private IIotCmdService iotCmdService;

    /**
     * 包字段服务
     */
    @Autowired
    private IotPacketServiceImpl iotPacketService;

    /**
     * 指令解码
     */
    @Autowired
    private IotCmdDecodeServiceImpl iotCmdDecodeService;

    /**
     * 指令编码
     */
    @Autowired
    private IotCmdEncoderServiceImpl iotCmdEncoderService;

    /**
     * 数据包字段服务
     */
    @Autowired
    private IotPacketFieldServiceImpl iotPacketFieldService;

    /**
     * 指令解释服务
     */
    @Autowired
    private IotCmdExplainServiceImpl iotCmdExplainService;


    /**
     * 查询指令列表
     */
    @RequiresPermissions("iot:cmd:list")
    @GetMapping("/list")
    public CmdVoInfo list(IotCmd iotCmd)
    {
        //报文map
        List<CmdPacketFieldVO> packetFields = getPacketFieldVo();
        startPage();
        List<IotCmd> list = iotCmdService.selectIotCmdList(iotCmd);
        CmdVoInfo rspData = new CmdVoInfo();
        rspData.setCode(200);
        rspData.setRows(list);
        rspData.setPacketList(iotPacketService.selectIotPacketList(new IotPacket()));
        rspData.setMsg("查询成功");
        rspData.setPacketFields(packetFields);
        rspData.setTotal((new PageInfo(list)).getTotal());
        System.out.println(JSON.toJSON(rspData));
        return rspData;
    }





    /**
     * 导出指令列表
     */
    @RequiresPermissions("iot:cmd:export")
    @Log(title = "指令", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, IotCmd iotCmd)
    {
        List<IotCmd> list = iotCmdService.selectIotCmdList(iotCmd);
        ExcelUtil<IotCmd> util = new ExcelUtil<IotCmd>(IotCmd.class);
        util.exportExcel(response, list, "指令数据");
    }

    /**
     * 获取指令详细信息
     */
    @RequiresPermissions("iot:cmd:query")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return AjaxResult.success(iotCmdService.selectIotCmdById(id));
    }



    /**
     * 获取解释的文本信息
     * @param cmdId 指令id
     * @return
     */
    @GetMapping(value = "explain/{id}")
    public AjaxResult getIotCmdExplain(@PathVariable("id") Long cmdId){
        IotCmdExplain iotCmdExplain = new IotCmdExplain();
        iotCmdExplain.setCmdId(cmdId);
        List<IotCmdExplain> cmdExplains =  iotCmdExplainService.selectIotCmdExplainList(iotCmdExplain);
        DevCmdVo devCmdVo = null;


        if(cmdExplains.size() == 0 ) {
            devCmdVo =  new DevCmdVo();
            JSONObject json = new JSONObject();
            json.put("tip","please config cmd");
            devCmdVo.setData(json);
        } else {

           String jsonStr =  cmdExplains.get(0).getJson();
            devCmdVo = JSON.parseObject(jsonStr,DevCmdVo.class);
        }

        return AjaxResult.success(devCmdVo);
    }


    /**
     * 新增指令
     */
    @RequiresPermissions("iot:cmd:add")
    @Log(title = "指令", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody IotCmd iotCmd)
    {
        return toAjax(iotCmdService.insertIotCmd(iotCmd));
    }

    /**
     * 修改指令
     */
    @RequiresPermissions("iot:cmd:edit")
    @Log(title = "指令", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody IotCmd iotCmd)
    {
        return toAjax(iotCmdService.updateIotCmd(iotCmd));
    }

    /**
     * 删除指令
     */
    @RequiresPermissions("iot:cmd:remove")
    @Log(title = "指令", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(iotCmdService.deleteIotCmdByIds(ids));
    }


    /**
     * 组装编码指令的字段
     * @param cmdEncodeJsonVo 指令编码数据
     * @return
     */
    @PostMapping("/generator/encode/json")
    public AjaxResult composeCmdEncode(@RequestBody CmdJsonEncodeVo cmdEncodeJsonVo){
        System.out.println(JSON.toJSON(cmdEncodeJsonVo));
        Long cmdId =  cmdEncodeJsonVo.getCmdId();

        //删除掉之前生成的指令逻辑字段
        IotCmdEncoder iotCmdEncoder = new IotCmdEncoder();
        iotCmdEncoder.setCmdId(cmdId);
        List<IotCmdEncoder> iotCmdEncoders = iotCmdEncoderService.selectIotCmdEncoderList(iotCmdEncoder);
        for(IotCmdEncoder item: iotCmdEncoders) {
            iotCmdDecodeService.deleteIotCmdDecodeById(item.getId());
        }


        //生成
        List<EncodeObj> encodeObjs =   cmdEncodeJsonVo.getEncodeObjs();
        for (EncodeObj encodeObj : encodeObjs) {
            IotCmdEncoder iotCmdEncoderDo = new IotCmdEncoder();
            iotCmdEncoderDo.setCmdId(cmdId);
            iotCmdEncoderDo.setSequence(encodeObj.getIndex().longValue());
            iotCmdEncoderDo.setFieldId(encodeObj.getFieldId());
            iotCmdEncoderDo.setRemark(encodeObj.getFieldName());
            iotCmdEncoderService.insertIotCmdEncoder(iotCmdEncoderDo);
        }
        DevCmdVo devCmdVo = generateCmdEncode(cmdEncodeJsonVo);
        //删除cmd解释表
        deleteCmdExplain(cmdId);
        //插入到解释框中
        insertCmdExplain(cmdId,devCmdVo);
        return AjaxResult.success(devCmdVo);
    }

    /**
     * 组装解码指令的字段
     * @param cmdJsonDecodeVo 指令解码vo
     * @return
     */
    @PostMapping("/generator/decode/json")
    public AjaxResult composeCmdDecode(@RequestBody CmdJsonDecodeVo cmdJsonDecodeVo){
        System.out.println(JSON.toJSON(cmdJsonDecodeVo));
        //指令cmdId
        Long cmdId =  cmdJsonDecodeVo.getCmdId();
        //删除掉之前生成的指令逻辑字段
        IotCmdDecode cmdDecode = new IotCmdDecode();
        cmdDecode.setCmdId(cmdId);
        List<IotCmdDecode> iotCmdDecodes = iotCmdDecodeService.selectIotCmdDecodeList(cmdDecode);
        for(IotCmdDecode item: iotCmdDecodes) {
            iotCmdDecodeService.deleteIotCmdDecodeById(item.getId());
        }
        //开始生成
        List<DecodeObj> decodeObjs =  cmdJsonDecodeVo.getDecodeObjs();
        for (DecodeObj decodeObj : decodeObjs) {
            IotCmdDecode iotCmdDecode = new IotCmdDecode();
            iotCmdDecode.setCmdId(cmdId);
            iotCmdDecode.setSequence(decodeObj.getIndex().longValue());
            iotCmdDecode.setTrimType(decodeObj.getTrimType().longValue());
            iotCmdDecode.setTrimParam(decodeObj.getTrimParam().longValue());
            iotCmdDecode.setFieldId(decodeObj.getFieldId().longValue());
            iotCmdDecode.setRemark(decodeObj.getFieldName());
            iotCmdDecodeService.insertIotCmdDecode(iotCmdDecode);
        }
        DevCmdVo devCmdVo = generateCmdDecode(cmdJsonDecodeVo);
        //删除cmd解释表
        deleteCmdExplain(cmdId);
        //插入到解释框中
        insertCmdExplain(cmdId,devCmdVo);

        return AjaxResult.success(devCmdVo);
    }


    /**
     * 获取包id 和 对应的 包字段列表
     * @return
     */
    private List<CmdPacketFieldVO> getPacketFieldVo() {
        List<CmdPacketFieldVO> cmdPacketFieldVOS = new ArrayList<>();
        IotPacket iotPacket = new IotPacket();
        List<IotPacket> packets = iotPacketService.selectIotPacketList(iotPacket);
        IotPacketField iotPacketField = new IotPacketField();
        for(IotPacket item : packets) {
            Long packetId = item.getId();
            iotPacketField.setPacketId(packetId);
            List<IotPacketField> packetFields = iotPacketFieldService.selectIotPacketFieldList(iotPacketField);
            List<IotPacketFieldVo> iotPacketFieldVos = new ArrayList<>();
            for(IotPacketField childItem: packetFields) {
                IotPacketFieldVo iotPacketFieldVo = new IotPacketFieldVo();
                BeanUtils.copyProperties(childItem, iotPacketFieldVo);
                iotPacketFieldVos.add(iotPacketFieldVo);
            }
            CmdPacketFieldVO cmdPacketFieldVO = new CmdPacketFieldVO();
            cmdPacketFieldVO.setPacketId(packetId + "");
            cmdPacketFieldVO.setPacketFieldVoList(iotPacketFieldVos);
            cmdPacketFieldVOS.add(cmdPacketFieldVO);
        }
        return cmdPacketFieldVOS;
    }


    /**
     * 删除cmd解释字段
     * @param cmdId
     */
    private void deleteCmdExplain(Long cmdId) {
        IotCmdExplain iotCmdExplain = new IotCmdExplain();
        iotCmdExplain.setCmdId(cmdId);
        List<IotCmdExplain> iotCmdExplains = iotCmdExplainService.selectIotCmdExplainList(iotCmdExplain);
        for(IotCmdExplain item: iotCmdExplains) {
            iotCmdExplainService.deleteIotCmdExplainById(item.getId());
        }
    }


    /**
     * 插入cmd的解释字段
     * @param cmdId
     */
    private void insertCmdExplain(Long cmdId,DevCmdVo devCmdVo) {
        IotCmd iotCmd = iotCmdService.selectIotCmdById(cmdId);
        String packetName = iotPacketService.selectIotPacketById(iotCmd.getPacketId()).getName();
        Long sponsor = iotCmd.getSponsor();
        IotCmdExplain iotCmdExplain = new IotCmdExplain();
        iotCmdExplain.setCmdId(cmdId);
        iotCmdExplain.setSponsor(sponsor);
        iotCmdExplain.setJson(JSON.toJSONString(devCmdVo));
        iotCmdExplain.setRemark(packetName + " ==> " + iotCmd.getRemark());
        iotCmdExplain.setCreator(1L);
        iotCmdExplain.setCreateDate(new Date());
        iotCmdExplainService.insertIotCmdExplain(iotCmdExplain);
    }


    /**
     * 生成指令解码json
     * @param cmdJsonDecodeVo 解码的数据
     * @return
     */
    private DevCmdVo generateCmdDecode(CmdJsonDecodeVo cmdJsonDecodeVo) {
        DevCmdVo devCmdVo = new DevCmdVo();
        devCmdVo.setDevId("sf00000001");
        devCmdVo.setCmdId(cmdJsonDecodeVo.getCmdId());
        JSONObject json = new JSONObject();
        List<DecodeObj> decodeObjs = cmdJsonDecodeVo.getDecodeObjs();
        for(DecodeObj item: decodeObjs) {
           Long fieldId =  item.getFieldId();
           IotPacketField iotPacketField =  iotPacketFieldService.selectIotPacketFieldById(fieldId);
           String fieldKey = iotPacketField.getField();
           Object fieldValue  = EField.getValue(iotPacketField.getFieldType().intValue());
           json.put(fieldKey,fieldValue);
        }
        devCmdVo.setData(json);
        return devCmdVo;
    }

    /**
     * 生成指令编码json
     * @param cmdEncodeJsonVo 编码的数据
     * @return
     */
    private DevCmdVo generateCmdEncode(CmdJsonEncodeVo cmdEncodeJsonVo) {
        DevCmdVo devCmdVo = new DevCmdVo();
        devCmdVo.setDevId("sf00000001");
        devCmdVo.setCmdId(cmdEncodeJsonVo.getCmdId());
        JSONObject json = new JSONObject();
        List<EncodeObj> encodeObjs = cmdEncodeJsonVo.getEncodeObjs();
        for(EncodeObj item: encodeObjs) {
            Long fieldId =  item.getFieldId();
            IotPacketField iotPacketField =  iotPacketFieldService.selectIotPacketFieldById(fieldId);
            String fieldKey = iotPacketField.getField();
            Object fieldValue  = EField.getValue(iotPacketField.getFieldType().intValue());
            json.put(fieldKey,fieldValue);
        }
        devCmdVo.setData(json);
        return devCmdVo;
    }


}
